<template>
  <div class="container">
    <!-- 菜单模块 -->
    <div class="oneCenter">
      <!-- 左侧菜单 -->
      <div class="leftMenu">
        <div class="allText" @click="clickAllMenu" :class="oneTitleActive == '全部' ? 'active' : ''">
          全部<span>({{ totalNum }})</span>
        </div>
        <div class="menuBox">
          <div class="oneMenuBox">
            <div class="oneMenu" :class="oneTitleActive == item.name ? 'active' : ''" @click="clickOneMenu(item)"
              v-for="item in menuList[0].children" :key="item.name">{{
                item.name }}</div>
          </div>
          <div class="twoMenuBox">
            <div class="twoMenu" :class="twoTitleActive == i.name ? 'active' : ''" @click="clickTwoMenu(i)"
              v-for="i in twoMenuList" :key="i.name">{{ i.name }}</div>
          </div>
        </div>
      </div>
      <!-- 右侧选项 -->
      <div class="rightContent">
        <span v-for="item in centerMenuList" @click="clickActiveDetails(item)"
          :class="activeDetails.name == item.name ? 'childItemActive' : ''" class="rightItem">{{
            removeNumberAndDot(item.name) }}</span>
      </div>
    </div>
    <!-- 图片展示模块 -->
    <div class="twoCenter" v-if="activeDetails == ''">
      <div class="classBox">
        <div class="itemCard" v-for="child in centerMenuList" @click="clickActiveDetails(child)" :key="child.name">
          <div class="listImgContent">
            <img :data-src="showResult_imagesIng(child)" v-lazy-img="showResult_imagesIng(child)"
              @error="setDefaultImage" alt="">
          </div>
          <div class="imgTitle">{{ child.arr[3] + "-" + removeNumberAndDot(child.arr[4]) }}</div>
        </div>
        <div class="itemCard" style="cursor: auto;" v-for="i in 4" :key="i"></div>
      </div>
    </div>
    <!-- 详情展示模块 -->
    <div class="threeCenter" v-else>
      <!-- 教程文档 -->
      <div class="showAllImage" @click="activeDetails = ''">
        <SvgIcon :svg="svgReturn" :size="24" />
        &nbsp;
        查看列表
      </div>
      <div class="title">{{ activeDetails?.arr[2] + "-" + activeDetails?.arr[3] + "-" +
        removeNumberAndDot(activeDetails?.arr[4]) }}
        <div class="Document" @click="goToDocument">教程文档</div>
      </div>
      <!-- 数据参数 -->
      <div class="showXLSX" v-if="activeDetails.children[1]?.count > 0">
        <div class="dataParams">
          数据参数:
        </div>
        <div class="UploadFiles">
          <div style="display: flex;width: 100%;">
            <div class="uploadTitle">上传文件</div>
            <div class="uploadContent" @click="openlpoadFile">
              <div class="showUploadText">
                <span v-if="singleFile.length < 1">
                  未选择文件
                </span>
                <span v-else v-for="item in singleFile">
                  {{ item.name }},&emsp;&emsp;
                </span>
              </div>
              <div class="showUploadSize">支持xlsx、csv、txt格式数据（小于5M）</div>
            </div>
            <div class="uploadButton">
              <span @click="downloadExample(activeDetails.children[1].children)">下载示例数据</span>
              <span @click="showExample = !showExample">查看示例数据</span>
              <!-- <div class="verifyBtn">
                <el-button type="primary" @click="uploadFile">验证数据</el-button>
              </div> -->
              <!-- 示例数据展示框 -->
              <el-dialog v-model="showExample" title="示例数据" width="90%" align-center>
                <div class="exampleBox">
                  <div v-for="item in activeDetails.children[1].children" :key="item.path">
                    <XlsxViewer :file-path="item.path"></XlsxViewer>
                  </div>
                </div>
              </el-dialog>
              <!-- 上传展示框 -->
              <el-dialog v-model="showUpload" title="上传文件" width="600px" align-center>
                <!-- 实现拖拽上传功能，showUploadText内展示上传文件名及文件大小 -->
                <Xupload v-model="singleFile" accept=".xlsx,.csv,.txt" hint="仅支持.xlsx,.csv,.txt格式" multiple="true" />
              </el-dialog>
            </div>
          </div>

          <div class="verifyBtn">
            <el-text :type="validateMessage == '文件上传成功' ? 'success' : 'danger'">{{ validateMessage }}</el-text>
            &emsp;
            <el-button v-if="validateMessage == ''" type="primary" @click="uploadFile">验证数据</el-button>
            <el-button v-else :type="validateMessage == '文件上传成功' ? 'success' : 'danger'"
              @click="uploadFile">验证数据</el-button>
          </div>
        </div>
      </div>
      <!-- 主要参数修改start======================================================== -->
      <div class="dataParams" v-if="activeDetails.children[2]?.count > 0">
        主要参数:
      </div>
      <div v-if="activeDetails.name == '2.叠加柱状图【宽型数据】'">
        <InputData v-model="inputReturnData" :data="configData" />
        <div class="InputConfirmButton">
          <el-button type="primary" @click="clickConfirm">确定</el-button>
        </div>
      </div>
      <div v-else>
        <div class="canshuImg" v-for="image in activeDetails.children[2]?.children" :key="image.path">
          <img :data-src="image.path" v-lazy-img="image.path" alt="">
        </div>
      </div>
      <!-- 主要参数修改end======================================================== -->
      <div class="dataParams">
        主要结果:
      </div>
      <div v-if="showImages" class="imgContent">
        <img :data-src="showIamgeOffset(drawChartData)" v-lazy-img="showIamgeOffset(drawChartData)" alt="">
        <div class="downloadImg">
          <el-button type="primary" @click="downloadImage(drawChartData)">下载图片</el-button>
        </div>
      </div>
      <div v-else>
        <div class="imgContent" v-for="img in activeDetails.children[3]?.children" :key="img.path">
          <img :data-src="showResult_images(img.path)" v-lazy-img="img.path" alt="">
          <!-- 下载图片 -->
          <!-- <div class="downloadImg">
            <el-button type="primary" @click="downloadImg(img.path)">下载图片</el-button>
          </div> -->
        </div>
        <div v-if="activeDetails.children[3]?.count == 0" class="imgError">
          <div class="error-message">
            <span class="error-icon">⚠️</span>
            暂无图片
          </div>
        </div>
      </div>
      <div class="dataParams" v-if="activeDetails.children[0]?.count > 0">
        代码展示:
      </div>
      <div class="showMd" v-for="md in activeDetails.children[0]?.children" :key="md.path">
        <MdViewer :file-path="md.path"></MdViewer>
      </div>
      <div class="dataParams">
        飞书链接：<br>
      </div>
      <div class="feishuUrl">
        <a :href="activeDetails.feishuLink" target="_blank">{{ activeDetails.feishuLink }}</a>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onBeforeMount, onMounted, watch } from "vue";

// 导入message提示组件
import { ElMessage } from 'element-plus'

import { testDataUpload, drawImage } from '@/api/index.js'
// 导入参数调整组件InputData.vue
import InputData from './components/InputData.vue'
import menuList from '@/utils/menuListFiles.js'// 脚本编译的文件路径
import { BASE_URL, BASE_URL_STATIC } from '@/utils/zongIp.js'// 静态资源IP地址
import defaultImage from '@/assets/default.webp';
// 导入本地svg图标
import svgReturn from '@/assets/svg/return.svg?raw';
const configData = ref({
  "柱": [
    {
      "name": "堆叠类型",
      "key": "stack_type",
      "value": ["百分比", "频数"],
      "type": "select"
    },
    {
      "name": "颜色",
      "key": "bar_colors",
      "value": [
        "#4E79A7", "#F28E2B", "#E15759", "#76B7B2",
        "#59A14F", "#EDC949", "#B07AA1", "#FF9DA7"
      ],
      "type": "checkbox"
    },
    {
      "name": "描边颜色",
      "key": "bar_edgecolor",
      "value": ["black", "white"],
      "type": "checkbox"
    },
    {
      "name": "描边粗细",
      "key": "bar_linewidths",
      "value": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0],
      "type": "select"
    },
    {
      "name": "宽度",
      "key": "bar_width",
      "value": "String",
      "type": "input"
    },
    {
      "name": "不透明度",
      "key": "bar_alpha",
      "value": [0, 1],
      "type": "input"
    }
  ],
  "连线": [
    {
      "name": "是否展示连线",
      "key": "show_lines",
      "value": false,
      "type": "switch"
    },
    {
      "name": "不透明度",
      "key": "lines_bar_alpha",
      "value": [0, 1],
      "type": "input"
    }
  ],
  "标注": [
    {
      "name": "标注映射",
      "key": "show_labels",
      "value": ["不映射", "频数映射"],
      "type": "select"

    },
    {
      "name": "大小",
      "key": "label_fontsize",
      "value": ["6pt", "7pt", "8pt", "9pt", "10pt", "11pt", "12pt", "14pt", "16pt", "18pt", "20pt"],
      "type": "select"
    },
    {
      "name": "方向",
      "key": "label_rotation",
      "value": ["水平", "纵向"],
      "type": "select"
    },
    {
      "name": "标签背景",
      "key": "label_bg",
      "value": false,
      "type": "switch"
    },
    {
      "name": "标签描边",
      "key": "label_stroke",
      "value": ["0.1pt", "0.2pt", "0.3pt", "0.4pt", "0.5pt", "0.6pt", "0.7pt", "0.8pt", "0.9pt", "1.0pt"],
      "type": "select"
    }
  ],
  "标题": [
    {
      "name": "大标题",
      "key": "main_title",
      "value": "String",
      "type": "input"
    },
    {
      "name": "x轴标题",
      "key": "xlabel",
      "value": "String",
      "type": "input"
    },
    {
      "name": "y轴标题",
      "key": "ylabel",
      "value": "String",
      "type": "input"
    }
  ],
  "图注": [
    {
      "name": "是否展示",
      "key": "show_legend",
      "value": true,
      "type": "switch"
    },
    {
      "name": "图注标题",
      "key": "legend_title",
      "value": "String",
      "type": "input"
    },
    {
      "name": "图注位置",
      "key": "legend_loc",
      "value": ["best", "upper right", "upper left", "lower right", "lower left"],
      "type": "select"
    }
  ],
  "坐标轴": [
    {
      "name": "x轴标注旋转",
      "key": "x_tick_rotation",
      "value": ["0", "45", "90"],
      "type": "select"
    },
    {
      "name": "y轴范围+刻度",
      "key": "y_ticks",
      "value": "逗号分隔",
      "type": "input_array"

    }
  ],
  "风格": [
    {
      "name": "边框",
      "key": "show_border",
      "value": false,
      "type": "switch"
    },
    {
      "name": "网格",
      "key": "show_grid",
      "value": false,
      "type": "switch"
    },
    {
      "name": "xy颠倒",
      "key": "invert_xy",
      "value": false,
      "type": "switch"
    },
    {
      "name": "文字大小",
      "key": "text_size",
      "value": ["6pt", "7pt", "8pt", "9pt", "10pt", "11pt", "12pt", "14pt", "16pt", "18pt", "20pt"],
      "type": "select"
    }
  ],
  "图片": [
    {
      "name": "宽度",
      "key": "fig_width",
      "value": "String",
      "type": "input"
    },
    {
      "name": "高度",
      "key": "fig_height",
      "value": "String",
      "type": "input"
    },
    {
      "name": "字体",
      "key": "font",
      "value": "SimHei",
      "type": "input"
    }
  ]
});
const inputReturnData = ref({});
const showUpload = ref(false);
const showExample = ref(false);
const dataUploadUrl = ref("");
const singleFile = ref([])
const openlpoadFile = () => {
  showUpload.value = true;
  // 清空当前选中数据
  singleFile.value = [];
}

const downloadExample = (urlList) => {
  for (let index = 0; index < urlList.length; index++) {
    const data = urlList[index];
    let url = data.path;
    console.log(url);
    // 通过fetch请求获取文件流，然后使用URL.createObjectURL创建一个URL，最后使用a标签的download属性下载文件
    fetch(url)
      .then(response => response.blob())
      .then(blob => {
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = data.name;
        a.click();
        URL.revokeObjectURL(url); // 释放URL对象
      });
  }
}
// 验证数据提示
const validateMessage = ref('')
// 上传文件并验证是否符合标准
const uploadFile = () => {
  let formData = new FormData();
  for (let i = 0; i < singleFile.value.length; i++) {
    const element = singleFile.value[i];
    console.log(element);
    formData.append('files', element);
  }
  dataUploadUrl.value = "";
  testDataUpload(formData).then(res => {
    if (res.success) {
      validateMessage.value = res.message;
      dataUploadUrl.value = res.data;
      // 验证通过
    } else {
      // element提示
      validateMessage.value = res.message;
      ElMessage.error(res.message);
    }
  })
  // console.log(singleFile.value);
}
const showImages = ref(false);
const drawChartData = ref();
// 绘制图片
const clickConfirm = () => {
  // 判断是否有上传的文件
  if (!dataUploadUrl.value) {
    ElMessage.error('请先完成数据验证');
    return;
  }
  let data = JSON.parse(JSON.stringify(inputReturnData.value));
  // 移除所有value值为null的属性
  Object.keys(data).forEach(key => {
    if (data[key] === null) {
      delete data[key];
    }
  });
  data.excel_file = dataUploadUrl.value;
  drawImage(data).then(res => {
    showImages.value = false;
    setTimeout(() => {
      showImages.value = true;
      drawChartData.value = res.data;
    }, 0);
  })
}
// 自定义懒加载指令
const vLazyImg = {
  mounted(el, binding) {
    const observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          // 当图片进入视口时加载图片
          el.src = binding.value;
          observer.unobserve(el); // 加载后停止观察

          // 图片加载完成后添加淡入效果
          el.onload = () => {
            el.style.opacity = 1;
          };
        }
      });
    }, {
      rootMargin: '100px', // 提前100px加载
      threshold: 0.01
    });

    observer.observe(el);

    // 存储observer以便组件卸载时清理
    el._lazyObserver = observer;
  },
  unmounted(el) {
    if (el._lazyObserver) {
      el._lazyObserver.unobserve(el);
    }
  }
};

const oneTitleActive = ref("全部");// 选中的一级菜单
const twoMenuList = ref([]);// 二级菜单列表
const twoTitleActive = ref("");// 选中的二级菜单
const centerMenuList = ref([]);// 展示的菜单列表
const activeDetails = ref('');// 选中的内容详情

/** 点击全部 */
const clickAllMenu = () => {
  oneTitleActive.value = "全部";
  twoTitleActive.value = "";
  twoMenuList.value = [];
  activeDetails.value = '';
  let list = []
  menuList[0].children.forEach(item => {
    item.children.forEach(i => {
      list.push(...i.children)
    })
  })
  centerMenuList.value = list;
}

/** 一级菜单点击事件 */
const clickOneMenu = (item) => {
  oneTitleActive.value = item.name;
  twoMenuList.value = item.children;
}

/** 二级菜单点击事件 */
const clickTwoMenu = (item) => {
  twoTitleActive.value = item.name;
  centerMenuList.value = item.children;
}

/** 点击Menu获取详情 */
const clickActiveDetails = (item) => {
  console.log(item);
  // 清空选中的文件
  singleFile.value = [];
  validateMessage.value = '';
  activeDetails.value = item;
}

/** 总数 */
const totalNum = ref(0);

/** 计算总数 */
const getTotalNum = () => {
  totalNum.value = 0;
  menuList[0].children.forEach(item => {
    if (item.children) {
      item.children.forEach(child => {
        totalNum.value += child.children.length;
      })
    }
  })
}

// 展示pdf
const goToDocument = () => {
  // 获取自己的url
  const currentUrl = window.location.href.split('#')[0];
  const baseUrl = currentUrl;
  // 构建正确的PDF路径
  let pdfPath = `${baseUrl}${activeDetails.value.children[4].path}`;
  // 在新窗口打开PDF
  window.open(pdfPath, '_blank');
}

const setDefaultImage = (e) => {
  e.target.src = defaultImage;
  e.target.onerror = null; // 防止循环报错
}
// 展示绘制完成的图片
const showIamgeOffset = (url) => {
  const path = url?.replace(/^\./, '');
  return BASE_URL_STATIC + path;
}
// 下载图片
const downloadImage = async (url) => {
  if (!url) {
    console.error('图片 URL 不能为空');
    return;
  }
  // 如果你的 BASE_URL_STATIC 是必要的，确保它是正确的完整地址
  const fullImageUrl = BASE_URL_STATIC + url.replace(/^\./, '');
  // 时间(年月日时分秒毫秒)+文件名
  const downloadName = url.split('/').pop();
  // 2. 发起 Fetch 请求，获取图片二进制数据
  fetch(fullImageUrl)
    .then(response => response.blob())
    .then(blob => {
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = downloadName;
      a.click();
      URL.revokeObjectURL(url); // 释放URL对象
    });
};
// 展示图片
const showResult_images = (url) => {
  // 判断是否是生产环境
  const isProduction = process.env.NODE_ENV === 'production';
  // 如果是生产环境，则使用BASE_URL
  let baseUrl = isProduction ? BASE_URL : '';
  return baseUrl + url;
}

/** 懒加载 */
const showResult_imagesIng = (item) => {
  // 判断是否是生产环境
  const isProduction = process.env.NODE_ENV === 'production';
  // 如果是生产环境，则使用BASE_URL
  let baseUrl = isProduction ? BASE_URL : '';
  if (item.children[3]?.children.length > 0) {
    const defaultImage = item.children[3].children[0].path;
    return baseUrl + defaultImage;
  }
}
// 去除数字和.
const removeNumberAndDot = (str) => {
  return str.replace(/\d+\.|\d+/g, '');
}
// 监听singleFile的变化
watch(singleFile, (newValue) => {
  if (newValue.length > 0) {
    // 关闭弹窗
    showUpload.value = false;
  }
});

onBeforeMount(() => {
  clickAllMenu();
  getTotalNum();
});
</script>

<style scoped lang="scss">
.container {
  width: calc(100% - 20px);
  padding: 0 10px;
  min-width: 1000px;
  margin: auto;
  height: 100%;

  // 主菜单
  .oneCenter {
    margin: auto;
    margin-top: 10px;
    height: 410px;
    display: flex;
    background-color: #fff;

    .leftMenu {
      width: 440px;
      height: 100%;
      font-size: 19px;
      font-weight: 700;
      color: #333;

      .allText {
        text-align: center;
        display: flex;
        justify-content: space-between;
        padding: 5px 10px;
        border-right: 1px solid #f0f0f0;
        cursor: pointer;
      }

      .menuBox {
        height: calc(100% - 40px);
        display: flex;
        border-top: 1px solid #f0f0f0;

        .oneMenuBox {
          width: 219px;
          overflow-y: auto;
          border-right: 1px solid #f0f0f0;

          .oneMenu {
            padding: 5px 10px;
            cursor: pointer;
          }
        }

        .twoMenuBox {
          width: 219px;
          overflow-y: auto;
          border-right: 1px solid #f0f0f0;

          .twoMenu {
            font-size: 17px;
            padding: 6.5px 10px;
            cursor: pointer;
          }
        }
      }

      .active {
        color: #133d98;
        background-color: #f0f0f0;
        position: relative;
      }
    }

    .rightContent {
      flex: 1;
      height: 100%;
      overflow-y: auto;

      .rightItem {
        padding: 5px 15px;
        margin: 5px 10px;
        font-weight: 400;
        display: inline-block;
        cursor: pointer;
        border-radius: 10px;

        &:hover {
          color: #133d98;
          background-color: #f3f7ff;
        }
      }

      .childItemActive {
        color: #133d98;
        background-color: #f3f7ff;
      }
    }
  }

  .twoCenter {
    margin-top: 10px;

    .classBox {
      display: flex;
      flex-wrap: wrap;
      justify-content: space-around;

      .itemCard {
        text-align: center;
        width: 200px;
        display: flex;
        flex-direction: column;
        margin: 5px;
        cursor: pointer;

        .listImgContent {
          width: 200px;
          height: 200px;

          img {
            width: 100%;
            height: 100%;
            box-shadow: 1px 1px 5px #ccc;
            border-radius: 5px;
            background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
            background-size: 200% 100%;
            animation: shimmer 1.5s infinite;
            opacity: 0;
            transition: opacity 0.3s ease;
          }
        }

        .imgTitle {
          margin-top: 5px;
          font-size: 13px;
        }
      }
    }
  }

  .threeCenter {
    background-color: #fff;

    .showAllImage {
      margin-top: 20px;
      padding: 15px;
      padding-bottom: 0px;
      display: flex;
      align-items: center;
      cursor: pointer;
      width: fit-content;
    }

    .title {
      padding: 10px;
      display: flex;
      justify-content: space-between;
      font-weight: 700;
      margin-left: 50px;

      .Document {
        color: #133d98;
        cursor: pointer;
      }
    }

    .dataParams {
      padding: 10px;
      font-weight: 700;
      display: flex;
      justify-content: space-between;
      background-color: #3082f5;
      border-radius: 15px 15px 0 0;
      color: #fff;
    }

    .imgError {
      max-width: 100%;
      border: 1px solid #e0e0e0;
      border-radius: 0 0 8px 8px;
      padding: 16px;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    }

    .showXLSX {
      padding-bottom: 12px;
    }

    // 上传文件
    .UploadFiles {
      padding: 15px;
      flex-direction: column;
      display: flex;

      // align-items: center;
      .uploadTitle {
        margin-top: 12px;
        font-size: 19px;
        margin-right: 15px;
      }

      .uploadContent {
        margin-top: 2px;
        width: calc(100% - 225px);

        .showUploadText {
          cursor: pointer;
          border-radius: 5px;
          border: 1px solid #e0e0e0;
          height: 40px;
          display: flex;
          align-items: center;
          padding-left: 10px;
        }

        .showUploadSize {
          color: #666;
        }
      }

      .uploadButton {
        color: #3082f5;
        font-weight: 700;
        line-height: 25px;
        margin-left: 15px;
        display: flex;
        flex-direction: column;

        span {
          cursor: pointer;

          &:hover {
            color: #4092e5;
            // 下划线
            text-decoration: underline;

          }
        }



        .exampleBox {
          display: flex;
          flex-direction: column;
          max-height: 80vh;

          // overflow-y: auto;
          >div {
            height: calc(45vh - 70px);
            flex: 1;
            border: 1px solid #e0e0e0;
            margin-top: 5px;
            display: flex;
            width: 100%;

            &:nth-child(1) {
              flex: 2;
            }
          }
        }
      }

      .verifyBtn {
        display: flex;
        justify-content: end;
        align-items: center;

        .el-button {
          margin-right: 25px;
        }
      }
    }

    .InputConfirmButton {
      text-align: right;
      margin-right: 10px;
      margin-bottom: 10px;
    }

    .imgContent {
      height: 500px;
      width: 100%;
      text-align: center;
      margin: 20px auto;
      position: relative;

      img {
        max-height: 100%;
        max-width: 100%;
        background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
        background-size: 200% 100%;
        animation: shimmer 1.5s infinite;
        opacity: 0;
        transition: opacity 0.3s ease;
      }

      .downloadImg {
        position: absolute;
        right: 10px;
        bottom: 10px;
        color: #4092e5;
        cursor: pointer;
      }
    }

    .canshuImg {
      width: 100%;
      text-align: center;
      margin: 20px auto;

      img {
        width: 100%;
        background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
        background-size: 200% 100%;
        animation: shimmer 1.5s infinite;
        opacity: 0;
        transition: opacity 0.3s ease;
      }
    }

    .showMd {
      margin-bottom: 20px;
    }

    .feishuUrl {
      margin: 0px 20px 30px 20px;
      padding: 30px 0px;
      text-align: center;
      font-weight: 700;
      width: calc(100% - 100px);
      cursor: pointer;
      text-decoration: underline;
      color: #666;
    }
  }
}

@keyframes shimmer {
  from {
    background-position: 200% 0;
  }

  to {
    background-position: -200% 0;
  }
}
</style>